#include "renderTree.h"

#include <iostream.h>
#include <math.h>
#include <cstdlib>
#include <QFile>

RenderTree::RenderTree(): AbstractRenderTree() {
	Renderer *r = new RotateRenderer();
	rendererMap["Rotate"]=r;

	r = new TranslateRenderer();
	rendererMap["Translate"]=r;

	//r = new TextureRenderer();
	r = new MovieRendererDelegate();
	rendererMap["Texture"]=r;

	r = new DiamondRenderer();
	rendererMap["Diamond"]=r;

	r = new RectangleRenderer();
	rendererMap["Rectangle"]=r;

	r = new BodyRenderer();
	rendererMap["Body"]=r;

	r = new ExtremityRenderer();
	rendererMap["Extremity"]=r;

	r = new LimbRenderer();
	rendererMap["Limb"]=r;

	r = new VideoDisplayRenderer();
	rendererMap["videoDisplay"]=r;

	r = new DisplayPanelRenderer();
	rendererMap["display"]=r;
}
RenderTree::~RenderTree() {}

void RenderTree::render(QGLWidget *gl,std::list<Renderable *> *list) {



	std::list<Renderable*>::iterator it;

	for (it = list->begin(); it!=list->end();++it) {
		Renderable *ren = (Renderable*)*it;
		render(gl,ren);
	}
}

void RenderTree::render(QGLWidget *gl,Renderable *o) {

	std::string name = o->renderer->get();

	//		printf(name.data());
	//		printf(" - rendering\n");
	if (rendererMap[name]!=0) {
		rendererMap[name]->render(gl,o,this);

	}
	else {
		printf("not found\n");
	}
}

void RenderTree::addRenderer(std::string name,Renderer *r) {
	rendererMap[name]=r;
}

Renderer::Renderer() {
}

Renderer::~Renderer() {
}

//void Renderer::render(QGLWidget *gl,QObject *o) {
//	printf("render\n");
//}

RotateRenderer::RotateRenderer() {
}

RotateRenderer::~RotateRenderer() {
}

void RotateRenderer::render(QGLWidget *gl,Renderable *o,AbstractRenderTree *re) {
	//		printf("renderRot\n");
	XYZInt *r = (XYZInt*)o;
	glRotated(r->x->get()/16.0 , 1.0, 0.0, 0.0);
	glRotated(r->y->get()/16.0 , 0.0, 1.0, 0.0);
	glRotated(r->z->get()/16.0 , 0.0, 0.0, 1.0);
	//     	printf("rot: %d %d %d\n",r->x->get(),r->y->get(),r->z->get());
}

TranslateRenderer::TranslateRenderer() {
}

TranslateRenderer::~TranslateRenderer() {
}

void TranslateRenderer::render(QGLWidget *gl,Renderable *o,AbstractRenderTree *re) {
	//		printf("renderTrans\n");
	XYZFloat *r = (XYZFloat*)o;
	//		printf("pos: %f %f %f\n",r->x->get(),r->y->get(),r->z->get());
	glTranslated(r->x->get() , r->y->get(), r->z->get());
}

TextureRenderer::TextureRenderer() {
	pic=0;
}

TextureRenderer::~TextureRenderer() {
}

void TextureRenderer::render(QGLWidget *gl,Renderable *o,AbstractRenderTree *r) {

	Texture *t = (Texture*)o;




	t->current->set(((int)(t->current->get()+1))%t->length->get());
	//		printf("renderTex\n");
	int num = (int)(t->current->get()+1);
	QString expand;
	expand.sprintf("%08d",num);
	//		printf(expand.toLatin1().data());
	QString fileName = QString::fromStdString(t->filebase->get());
	fileName = fileName.arg(expand);
	//     printf(fileName.toLatin1().data());
	if (pic==0)
		pic = new QImage();

	pic->load(fileName);
	//printf("loadTime %d\n",localTime.elapsed());

	//     if (pic->load(fileName)==TRUE)
	//     {
	//     	printf("\nLOADED");
	//     }
	//printf("\ncolors %d\n",pic->numColors());
	QImage i = gl->convertToGLFormat(*pic);

	glDeleteTextures(1,&texture);
	glGenTextures( 1, &texture );
	glBindTexture( GL_TEXTURE_2D, texture );
	glTexImage2D( GL_TEXTURE_2D, 0, 3, pic->width(), pic->height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, i.bits() );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
	//texture = gl->bindTexture(*pic,GL_TEXTURE_2D);
	//printf("bindTime %d\n",localTime.elapsed());
	//	gl->bindTexture(*pic,GL_TEXTURE_2D);
	//	glBindTexture(GL_TEXTURE_2D, texture);

	//printf("bindTime2 %d\n",localTime.elapsed());
}




DiamondRenderer::DiamondRenderer() {
}

DiamondRenderer::~DiamondRenderer() {
}

void DiamondRenderer::render(QGLWidget *gl,Renderable *o,AbstractRenderTree *r) {
	printf("Diamod\n");
	glBegin(GL_QUADS);
	GLdouble cx=0;
	GLdouble cy=0;
	GLdouble cz=0;
	unsigned int corners=500;
	GLdouble bottomz = -0.2;
	GLdouble topz = 0.2;
	float i;
	GLdouble cornerx1,cornery1;
	GLdouble cornerx2 = 0.2;
	GLdouble cornery2 = 0;
	float delta = 1.0/corners;

	for (i=1;i<=corners+1;i++) {
		//cout << "valuex "<<cornerx2<<"\n"<< "valuey "<<cornery2<<"\n";
		cornerx1 = cornerx2;
		cornery1 = cornery2;
		cornerx2 = sin((i/corners)*M_PI*2)*0.2;
		cornery2 = cos((i/corners)*M_PI*2)*0.2;
		//cout << "valuex "<<(i/corners)<<"\n"<< "valuey "<<(i/4)*M_PI<<"\n";

		glTexCoord2d(delta*i,0);
		glVertex3d(cx, cy, bottomz);
		glTexCoord2d(delta*(i+1),0);
		glVertex3d(cx,cy, bottomz);

		glTexCoord2d(delta*(i+1),0.5);
		glVertex3d(cornerx2,cornery2,cz);
		glTexCoord2d(delta*i,0.5);
		glVertex3d(cornerx1,cornery1,cz);

	}
	for (i=1;i<=corners+1;i++) {
		//cout << "valuex "<<cornerx2<<"\n"<< "valuey "<<cornery2<<"\n";
		cornerx1 = cornerx2;
		cornery1 = cornery2;
		cornerx2 = sin((i/corners)*M_PI*2)*0.2;
		cornery2 = cos((i/corners)*M_PI*2)*0.2;
		//cout << "valuex "<<(i/corners)<<"\n"<< "valuey "<<(i/4)*M_PI<<"\n";

		glTexCoord2d(delta*i,1);
		glVertex3d(cx, cy, topz);
		glTexCoord2d(delta*(i+1),1);
		glVertex3d(cx,cy, topz);

		glTexCoord2d(delta*(i+1),0.5);
		glVertex3d(cornerx2,cornery2,cz);
		glTexCoord2d(delta*i,0.5);
		glVertex3d(cornerx1,cornery1,cz);

	}
	glEnd();
}


RectangleRenderer::RectangleRenderer(){}
RectangleRenderer::~RectangleRenderer(){}

void RectangleRenderer::render(QGLWidget *gl,Renderable *o,AbstractRenderTree *re){

	Rectangle *r = (Rectangle*)o;
//	printf("rect %f %f %f %f\n",r->offSetX->get(),r->offSetY->get(),r->w->get(),r->h->get());
	int mirror = r->mirror->get();
	glBegin(GL_QUADS);
//	glTexCoord2d(0,0);
	if (mirror==1)
		glTexCoord2d(1,0);
	else
		glTexCoord2d(0,0);
	glVertex3d(r->offSetX->get(), r->offSetY->get(), 0);
	if (mirror==1)
		glTexCoord2d(1,1);
	else
		glTexCoord2d(0,1);
	glVertex3d(r->offSetX->get(), r->h->get()+r->offSetY->get(), 0);

	if (mirror==1)
		glTexCoord2d(0,1);
	else
		glTexCoord2d(1,1);
	glVertex3d(r->w->get()+r->offSetX->get(), r->h->get()+r->offSetY->get(), 0);
//
	if (mirror==1)
		glTexCoord2d(0,0);
	else
		glTexCoord2d(1,0);
	glVertex3d(r->w->get()+r->offSetX->get(), r->offSetY->get(), 0);
	glEnd();
	glPushMatrix();
//	int i;
//	for (i=0;i<10;i++) {
//
//		glTranslated(0,0,-0.1);
//		glBegin(GL_QUADS);
//		glTexCoord2d(0,0);
//		glVertex3d(r->offSetX->get(), r->offSetY->get(), 0);
//		glTexCoord2d(0,1);
//		glVertex3d(r->offSetX->get(), r->h->get()+r->offSetY->get(), 0);
//		glTexCoord2d(1,1);
//		glVertex3d(r->w->get()+r->offSetX->get(), r->h->get()+r->offSetY->get(), 0);
//		glTexCoord2d(1,0);
//		glVertex3d(r->w->get()+r->offSetX->get(), r->offSetY->get(), 0);
//		glEnd();
//	}
	glPopMatrix();
}
